package com.android.server.mock.performer;

import android.annotation.NonNull;
import android.annotation.Nullable;
import org.json.JSONException;
import org.json.JSONObject;

import java.lang.reflect.Constructor;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

abstract class AbsPerformer<T> {
    private static final Map<Class<?>, Object> instances = new ConcurrentHashMap<>();

    protected AbsPerformer() {
        if (instances.containsKey(this.getClass())) {
            throw new IllegalStateException("Singleton instance already created");
        }
    }

    @SuppressWarnings("unchecked")
    public static <T> T getInstance(Class<T> clazz) {
        Object instance = instances.get(clazz);
        if (instance == null) {
            //noinspection SynchronizationOnLocalVariableOrMethodParameter
            synchronized (clazz) {
                instance = instances.get(clazz);
                if (instance == null) {
                    try {
                        Constructor<T> constructor = clazz.getDeclaredConstructor();
                        constructor.setAccessible(true);
                        instance = constructor.newInstance();
                        instances.put(clazz, instance);
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        }
        return (T) instance;
    }

    public String getString(JSONObject json, String key) {
        try {
            return json.getString(key);
        } catch (JSONException e) {
            return null;
        }
    }

    @NonNull
    public boolean getBool(@Nullable JSONObject json, String key) {
        return getBool(json, key, false);
    }

    @NonNull
    public boolean getBool(@Nullable JSONObject json, String key, boolean defValue) {
        try {
            return json.getBoolean(key);
        } catch (Exception e) {
            return defValue;
        }
    }

    @NonNull
    public int getInt(@Nullable JSONObject json, String key) {
        return getInt(json, key, 0);
    }

    @NonNull
    public int getInt(@Nullable JSONObject json, String key, int defValue) {
        try {
            return json.getInt(key);
        } catch (Exception e) {
            return defValue;
        }
    }

    @NonNull
    public long getLong(@Nullable JSONObject json, String key) {
        return getLong(json, key, 0L);
    }

    @NonNull
    public long getLong(@Nullable JSONObject json, String key, long defValue) {
        try {
            return json.getLong(key);
        } catch (Exception e) {
            return defValue;
        }
    }

    @NonNull
    public double getDouble(@Nullable JSONObject json, String key) {
        return getDouble(json, key, 0.0);
    }

    @NonNull
    public double getDouble(@Nullable JSONObject json, String key, double defValue) {
        try {
            return json.getDouble(key);
        } catch (Exception e) {
            return defValue;
        }
    }
}